package mockup;

import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Locale;

import miscellaneous.Storage;

import data.Appointment;
import data.Data;
import data.Invite;
import data.Meeting;
import data.Message;
import data.User;
import data.room.Reservation;
import data.room.Room;

/**
 * Converts a mockup to a 'real' data object. 
 * It automatically fetches needed objects from the appropriate list
 * and stitches the objects together to for a coherent data object to return.
 * @author Erik
 *
 */
public class MockupToData {

	/**
	 * Returns a 'real' data object for the mockup object.
	 * All pointers to other objects are filled in, and the
	 * returned object is fully coherent (if the needed objects
	 * exists). 
	 * @param mockup The mockup to convert to a data object
	 * @return A data object with all values and pointers correctly set (if the needed objects exists)
	 */
	public static Data getData(Mockup mockup) {
		if(mockup instanceof MeetingMockup)
			return getMeeting((MeetingMockup)mockup);
		else if(mockup instanceof AppointmentMockup)
			return getAppointment((AppointmentMockup)mockup);
		else if(mockup instanceof RoomMockup)
			return getRoom((RoomMockup)mockup);
		else if(mockup instanceof UserMockup)
			return getUser((UserMockup)mockup);
		else if(mockup instanceof InviteMockup)
			return getInvite((InviteMockup)mockup);
		else if(mockup instanceof MessageMockup)
			return getMessage((MessageMockup)mockup);
		
		System.err.println("The class " + mockup.getClass().getName() + " is unsupported in MockupToData");
		return null;
	}

	/**
	 * Returns a 'real' data object for the mockup object.
	 * All pointers to other objects are filled in, and the
	 * returned object is fully coherent (if the needed objects
	 * exists). 
	 * @param mockup The mockup to convert to a data object
	 * @return A data object with all values and pointers correctly set (if the needed objects exists)
	 */
	public static Message getMessage(MessageMockup mockup) {
		if(Storage.messages.contains(mockup.getId()))
			return Storage.messages.getById(mockup.getId());
		
		GregorianCalendar sendTime = new GregorianCalendar(Locale.FRANCE);
		sendTime.setTimeInMillis(mockup.getSendTime());
		
		GregorianCalendar readTime = new GregorianCalendar(Locale.FRANCE);
		readTime.setTimeInMillis(mockup.getReadTime());
		
		Message message = new Message(null, null, mockup.getSubject(), 
				mockup.getDescription(),sendTime, readTime);
		message.setId(mockup.getId());
		
		Meeting received = Storage.meetings.getById(mockup.getMeeting());
		if(received == null)
			System.err.println("MockupToData::getMessage: got a meeting that is null");
		
		message.setMeeting((Meeting)received);
		
		User user = Storage.users.getById(mockup.getReceiver());
		if(user == null)
			System.err.println("MockupToData::getMessage: got a user that is null");
		message.setReceiver(user);
		
		return message;
		
	}

	/**
	 * Returns a 'real' data object for the mockup object.
	 * All pointers to other objects are filled in, and the
	 * returned object is fully coherent (if the needed objects
	 * exists). 
	 * @param mockup The mockup to convert to a data object
	 * @return A data object with all values and pointers correctly set (if the needed objects exists)
	 */
	public static Invite getInvite(InviteMockup mockup) {
		if(Storage.messages.contains(mockup.getId()))
			return (Invite)Storage.messages.getById(mockup.getId());
		GregorianCalendar sendTime = new GregorianCalendar(Locale.FRANCE);
		sendTime.setTimeInMillis(mockup.getSendTime());
		
		GregorianCalendar readTime = new GregorianCalendar(Locale.FRANCE);
		readTime.setTimeInMillis(mockup.getReadTime());
		
		Invite invite = new Invite(null, null, mockup.getSubject(), 
				mockup.getDescription(), sendTime, readTime);
		
		invite.setId(mockup.getId());
		
		invite.setAnswer(mockup.getAnswer());
		
		Meeting received = Storage.meetings.getById(mockup.getMeeting());
		if(received == null)
			System.err.println("MockupToData::getInvite: got a meeting that is null");
		
		invite.setMeeting((Meeting)received);
		
		User user = Storage.users.getById(mockup.getReceiver());
		if(user == null)
			System.err.println("MockupToData::getInvite: got a user that is null");
		invite.setReceiver(user);

		return invite;
	}

	/**
	 * Returns a 'real' data object for the mockup object.
	 * All pointers to other objects are filled in, and the
	 * returned object is fully coherent (if the needed objects
	 * exists). 
	 * @param mockup The mockup to convert to a data object
	 * @return A data object with all values and pointers correctly set (if the needed objects exists)
	 */
	public static User getUser(UserMockup mockup) {
		if(Storage.users.contains(mockup.getId()))
			return Storage.users.getById(mockup.getId());
		
		User user = new User(mockup.getId(), mockup.getName(), null, mockup.getEmail(), mockup.getPhone(), mockup.getDepartment());
		
		GregorianCalendar birth = new GregorianCalendar(Locale.FRANCE);
		birth.setTimeInMillis(mockup.getDateOfBirth());
		user.setDateOfBirth(birth);
		
		return user;
	}

	/**
	 * Returns a 'real' data object for the mockup object.
	 * All pointers to other objects are filled in, and the
	 * returned object is fully coherent (if the needed objects
	 * exists). 
	 * @param mockup The mockup to convert to a data object
	 * @return A data object with all values and pointers correctly set (if the needed objects exists)
	 */
	public static Room getRoom(RoomMockup mockup) {
		if(Storage.rooms.containsKey(mockup.getId())) {
			return Storage.rooms.get(mockup.getId());
		}
		
		Room room = new Room(mockup.getName(), mockup.getLocation(), mockup.getCasualName(), mockup.getDescription(), mockup.getCapacity());
		room.setId(mockup.getId());
		
		return room;
	}
	
	/**
	 * Returns a 'real' data object for the mockup object.
	 * All pointers to other objects are filled in, and the
	 * returned object is fully coherent (if the needed objects
	 * exists). 
	 * @param mockup The mockup to convert to a data object
	 * @return A data object with all values and pointers correctly set (if the needed objects exists)
	 */
	public static Appointment getAppointment(AppointmentMockup mockup) {
		if(Storage.appointments.contains(mockup.getId()))
			return Storage.appointments.getById(mockup.getId());
		
		Appointment app = new Appointment(mockup.getTitle(), mockup.getDescription(), mockup.getLocation(), null, null);
		app.setId(mockup.getId());
		
		User user = Storage.users.getById(mockup.getOwnerID());
		if(user == null)
			System.err.println("MockupToData::getAppointment: got a user that is null");
		app.setOwner(user);
		
		Reservation res = getReservation(mockup.getReservation());
		app.setReservation(res);
		
		if(res != null) 
			res.setAppointment(app);
		else
			System.err.println("MockupToData::getAppointment: got a reservation that is null");
		
		return app;
	}

	/**
	 * Returns a 'real' data object for the mockup object.
	 * All pointers to other objects are filled in, and the
	 * returned object is fully coherent (if the needed objects
	 * exists). 
	 * @param mockup The mockup to convert to a data object
	 * @return A data object with all values and pointers correctly set (if the needed objects exists)
	 */
	public static Reservation getReservation(ReservationMockup mockup) {
		if(Storage.reservations.containsKey(mockup.getId())) {
			return Storage.reservations.get(mockup.getId());
		}
		
		Reservation res = new Reservation(null, null, null);
		res.setId(mockup.getId());
		
		GregorianCalendar startTime = new GregorianCalendar(Locale.FRANCE);
		startTime.setTimeInMillis(mockup.getStartTime());
		res.setStartTime(startTime);
		
		GregorianCalendar endTime = new GregorianCalendar(Locale.FRANCE);
		endTime.setTimeInMillis(mockup.getEndTime());
		res.setEndTime(endTime);
	
		if(mockup.getRoomID() > 0) { 
			Room room = null;
			if(Storage.rooms.containsKey(mockup.getRoomID())) {
				room = Storage.rooms.get(mockup.getRoomID());
			}			
			res.setRom(room);
		}
	
		return res;
		
	}
	
	/**
	 * Returns a 'real' data object for the mockup object.
	 * All pointers to other objects are filled in, and the
	 * returned object is fully coherent (if the needed objects
	 * exists). 
	 * @param mockup The mockup to convert to a data object
	 * @return A data object with all values and pointers correctly set (if the needed objects exists)
	 */
	public static Meeting getMeeting(MeetingMockup mockup) {
		if(Storage.meetings.contains(mockup.getId()))
			return Storage.meetings.getById(mockup.getId());
		
		Meeting meeting = new Meeting(mockup.getTitle(), mockup.getDescription(), mockup.getLocation(), null, null, null);
		meeting.setId(mockup.getId());
		
		User user = Storage.users.getById(mockup.getOwnerID());
		if(user == null)
			System.err.println("MockupToData::getMeeting: got a user that is null");
		meeting.setOwner(user);
		
		Reservation res = getReservation(mockup.getReservation());
		meeting.setReservation(res);
		if(res == null) 
			System.err.println("MockupToData::getMeeting: got a reservation that is null");
		
		List<User> list = new ArrayList<User>();
		for(int i : mockup.getParticipants()) {
			User part = Storage.users.getById(i);
			if(part == null)
				System.err.println("MockupToData::getMeeting: got a participant that is null");
			list.add(part);
		}
		meeting.setParticipants(list);
		
		return meeting;
	}
}
